package genedit.view.graph;

import java.awt.BasicStroke;
import java.awt.Color;
import java.awt.Font;
import java.awt.FontMetrics;
import java.awt.Graphics2D;
import java.awt.Paint;
import java.awt.Stroke;
import java.awt.geom.AffineTransform;
import java.awt.geom.GeneralPath;
import java.awt.geom.Rectangle2D;
import java.util.ArrayList;

import genedit.model.graph.GraphElement;
import genedit.model.graph.Point;
import genedit.model.graph.classModel.AggregationLink;

public class AggregationLinkPainter extends LinkPainter {

	public AggregationLinkPainter(GraphElement element) {
		super(element);
	}
	
	@Override
	public void paint(Graphics2D g) {
		super.paint(g);
		AggregationLink link = (AggregationLink) element;
		Color backupColor=g.getColor();
		g.setColor(link.getColor());
		Stroke backupStroke = g.getStroke();
		Paint backupPaint = g.getPaint();
		
		if (link.getEnd() == null) {
			g.setStroke(new BasicStroke(1f, BasicStroke.CAP_BUTT, BasicStroke.JOIN_BEVEL, 0,
					new float[] { 2, 2 }, 0));
		}
		ArrayList<Point> points = link.getAllPoints();
		// ako zelimo da se icrtavaju sve linije ovaj faktor je 0
		int factor = 0;
		if (link.getEnd() != null)
			factor = 1;
		for (int i = 0 + factor; i < points.size() - 1 - factor; i++) {
			g.drawLine((int) points.get(i).getPosition().getX(), (int) points.get(i).getPosition()
					.getY(), (int) points.get(i + 1).getPosition().getX(), (int) points.get(i + 1)
					.getPosition().getY());
		}
		for (Point p : points) {
			// preskoci crtanje pocetnih tacaka
			if (p.equals(link.getStart()) || p.equals(link.getEnd()))
				continue;
			g.fillRect((int) p.getPosition().getX() - rectDim, (int) p.getPosition().getY()
					- rectDim, rectEdge, rectEdge);
		}

		// ako je veza zavrsena crtaj strelice
		link = (AggregationLink) getElement();
		if (link.getEnd() != null && link.getBreakPoints().size() > 1) {
			AffineTransform backup = g.getTransform();
			AffineTransform newTrans = new AffineTransform(backup);
			int arrowSize = 10;
			Point breakPoint;
			double angle;
			int roleNameTextHeight;
			int roleNameTextWidth;
			int cardinalityTextWidth;
			FontMetrics fm;
			Rectangle2D rectangleRoleName;
			Rectangle2D rectangleCardinality;
					
			// strelica na pocetku
			if(link.getStartNavigable()) {
				breakPoint = points.get(1);
				newTrans.translate(breakPoint.getPosition().getX(), breakPoint.getPosition().getY());
				newTrans.rotate(getAngleOfLineBetweenTwoPoints(breakPoint, points.get(2)));
				angle = getAngleOfLineBetweenTwoPoints(breakPoint, points.get(2));
				g.setTransform(newTrans);
				g.setStroke(new BasicStroke(2f));
					
				GeneralPath p0 = new GeneralPath();
				p0.moveTo(0.0f, 0.0f);
				p0.lineTo(-10.0f, 10.0f);
				p0.lineTo(0.0f, 20.0f);
				p0.lineTo(10.0f, 10.0f);
				p0.closePath();
				g.draw(p0);
				g.setColor(Color.BLACK);
				g.setPaint(Color.WHITE);
				g.setPaintMode();
				g.fill(p0);
				g.setColor(backupColor);
				g.setPaint(backupPaint);
				g.setStroke(backupStroke);
				
				g.setFont(new Font("Arial",Font.BOLD,9));
						
				//uzimaju se dimenzije stringa za RoleName i Cardinality kako ne bi doslo do
				//preklapanja stringa koji se ispisuje sa objektima
				fm = g.getFontMetrics(g.getFont());
				rectangleRoleName = fm.getStringBounds(link.getRoleNameStart(), g);
				rectangleCardinality = fm.getStringBounds(link.getMultiplicityStart(), g);
				roleNameTextHeight = (int)(rectangleRoleName.getHeight());
				roleNameTextWidth = (int)(rectangleRoleName.getWidth());
				cardinalityTextWidth = (int)(rectangleCardinality.getWidth());
						
				if(angle == 0) {
					g.drawString(link.getMultiplicityStart(), 15, 15);
					g.drawString(link.getRoleNameStart(), 15, 15 + roleNameTextHeight);
				} else if (angle == -Math.PI){
					newTrans.rotate(Math.PI);
					newTrans.translate(0, -30);
					g.setTransform(newTrans);
					g.drawString(link.getMultiplicityStart(), 15, 15);
					g.drawString(link.getRoleNameStart(), 15, 15 + roleNameTextHeight);
				} else if (angle == -Math.PI/2) {
					newTrans.rotate(Math.PI/2);
					newTrans.translate(0, -30);
					g.setTransform(newTrans);
					g.drawString(link.getMultiplicityStart(), 15, 15);
					g.drawString(link.getRoleNameStart(), 15, 15 + roleNameTextHeight);
				} else {
					newTrans.rotate(-Math.PI/2);
					newTrans.translate(0, -30);
					g.setTransform(newTrans);
					g.drawString(link.getMultiplicityStart(), -cardinalityTextWidth - 15 - roleNameTextWidth, 15);
					g.drawString(link.getRoleNameStart(), -cardinalityTextWidth - 15 - roleNameTextWidth, 15 + roleNameTextHeight);
				}
			}
					
					// strelica na kraju
			if(link.getEndNavigable()) {
				newTrans = new AffineTransform(backup);
				breakPoint = points.get(points.size() - 2);
				newTrans.translate(breakPoint.getPosition().getX(), breakPoint.getPosition().getY());
				newTrans.rotate(getAngleOfLineBetweenTwoPoints(breakPoint,
						points.get(points.size() - 3)));
				angle = getAngleOfLineBetweenTwoPoints(breakPoint, points.get(points.size() - 3));
				g.setTransform(newTrans);
				g.drawLine(0, 0, -arrowSize, arrowSize);
				g.drawLine(0, 0, arrowSize, arrowSize);
						
				g.setFont(new Font("Arial",Font.BOLD,9));
						
				//uzimaju se dimenzije stringa za RoleName i Cardinality kako ne bi doslo do
				//preklapanja stringa koji se ispisuje sa objektima
				fm = g.getFontMetrics(g.getFont());
				rectangleRoleName = fm.getStringBounds(link.getRoleNameEnd(), g);
				rectangleCardinality = fm.getStringBounds(link.getMultiplicityEnd(), g);
				roleNameTextHeight = (int)(rectangleRoleName.getHeight());
				roleNameTextWidth = (int)(rectangleRoleName.getWidth());
				cardinalityTextWidth = (int)(rectangleCardinality.getWidth());
						
				if(angle == 0) {
					g.drawString(link.getMultiplicityEnd(), 15, 15);
					g.drawString(link.getRoleNameEnd(), 15, 15 + roleNameTextHeight);
				} else if (angle == -Math.PI){
					newTrans.rotate(Math.PI);
					newTrans.translate(0, -30);
					g.setTransform(newTrans);
					g.drawString(link.getMultiplicityEnd(), 15, 15);
					g.drawString(link.getRoleNameEnd(), 15, 15 + roleNameTextHeight);
				} else if (angle == -Math.PI/2) {
					newTrans.rotate(Math.PI/2);
					newTrans.translate(0, -30);
					g.setTransform(newTrans);
					g.drawString(link.getMultiplicityEnd(), 15, 15);
					g.drawString(link.getRoleNameEnd(), 15, 15 + roleNameTextHeight);
				} else {
					newTrans.rotate(-Math.PI/2);
					newTrans.translate(0, -30);
					g.setTransform(newTrans);
					g.drawString(link.getMultiplicityEnd(), -cardinalityTextWidth - 15 - roleNameTextWidth, 15);
					g.drawString(link.getRoleNameEnd(), -cardinalityTextWidth - 15 - roleNameTextWidth, 15 + roleNameTextHeight);
				}
			}
			
			g.setTransform(backup);
		}

		g.setStroke(backupStroke);
		g.setColor(backupColor);
	}

}
